/*
 * Copyright (c) 2013. Kevin Lee (http://182.92.183.142/).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.demo;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

import com.utils.BASE64Util;
import com.utils.EncException;
import com.utils.MD5;
import com.utils.PayEncrypt;
import com.utils.PaySign;
import com.utils.RSAUtil;
import com.utils.StringUtil;


/**
 * Created with IntelliJ IDEA. User: kevin Date: 13-7-7 Time: 上午11:46
 * Email:lishu5566@gmail.com
 */
public class EncryptManager {
	public static final String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALHxfVnADIl8LZPlZM/9EcTpgcH7WBj4QUp/ElzDKAEG8YzpMQdWYRFHN+M83pNlj6bhfl/tP86+e1iaG6Hhxb8rLK6l6kGxfZNmWKmpIWIYU4iE4f+ISuWcogvTdqr2u3fkymLEbkyJTQsHSCsbEP/A1uLUQomPcgGMyCcc6DdzAgMBAAECgYB7jPE8H9yUmWQMDHqy70QnNPqjdaD1tWmgEBrvzZE5JVkSPdeNAKzlEk37uYfRT/MuK+NTN6fWJOv/2QDWpaxmphMmKM/OAOy6grFwELGRSSS7Iq+6pgMznd6LWjTj2OrETgJN24WkHAx6DlsI6qHLZv0vOIUSNOu4HqxNWznyAQJBAOrqG47YRUeTl8sjira2IO3jXc03H/JbD7N1miaUQzuxrULO+M6Oh+mlVQbQRujtmvZDXR/cbultiT+6I8u5WGcCQQDB6kq91TAq7wyfR+sWPEGOOtq+RHPOelAk1z0l3Ke+MlBBFvtBYE9qdBk59WuLjU5rHPBW2Z8u2braWhjgzfEVAkAh05YmSpQnS2R3NuX5i15QgwX1z/NEtcIcCForJfxMczhMv3rqW3HMvibxNTqQve4reeXF+brq2AAEcixHYKgPAkEAsrx47ebuAfTbRolsp88cgbO/4faIY74b1wlJxHdRah9IF+bN6qGSMcYXZnPPEA9MQ7Cl2ve2IOHxt8ep/LP2TQJAUOkbTWy9vgPudsL+wbeYu6szxnNenw6sCSoxtVYgXmpzUM6KuvIvoJh5Z0kgTnNfkooRuZW5ICrejEs2AJFO0Q==";
	// public static final String publicKey =
	// "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW0bfUQVUouffhqN6GX9GtGcSBVpPe/MJAtZOln/+jhCejzAcgNPVtcJY3agag6LW/CPcGwsD01U9dY/zkf6cAFU0az7AvMV90M7gGWioIUwEjvdGu7qOfCLFKBBcQ3Umt4fyuHLspxB1cxwcUf1HvJ1ngzpvkeybp+8XC9qbrzQIDAQAB";
	public static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx8X1ZwAyJfC2T5WTP/RHE6YHB+1gY+EFKfxJcwygBBvGM6TEHVmERRzfjPN6TZY+m4X5f7T/OvntYmhuh4cW/KyyupepBsX2TZlipqSFiGFOIhOH/iErlnKIL03aq9rt35MpixG5MiU0LB0grGxD/wNbi1EKJj3IBjMgnHOg3cwIDAQAB";
	private String pingKey = null;
	private String workKey = null;
	private String mobKey = null;

	public EncryptManager() {

	}

	/**
	 * 初始化加密管理者， 1.生成加密秘钥 2.生成验签秘钥
	 * 
	 * @throws Exception
	 */
	public void initEncrypt() throws Exception {
		pingKey = StringUtil.getRandomString(24);
		workKey = StringUtil.getRandomString(24);
		setMobKey(pingKey, workKey);
	}

	/**
	 * 返回加密秘钥
	 * 
	 * @return
	 */
	public String getPingKey() {
		return pingKey;
	}

	/**
	 * 返回验签秘钥
	 * 
	 * @return
	 */
	public String getWorkKey() {
		return workKey;
	}

	/**
	 * 默默的设置RAS加密
	 * 
	 * @param pingKey
	 * @param workKey
	 * @throws Exception
	 */
	private void setMobKey(String pingKey, String workKey) throws Exception {
		mobKey = encryptKey(pingKey + workKey);
	}

	/**
	 * 返回加密的秘钥保护字段
	 * 
	 * @return
	 */
	public String getMobKey() {
		return mobKey;
	}

	/**
	 * 先Md5再Base64加密 用于密码加密
	 */
	public String encryptByMd5AndBASE64(String pwd) {
		try {
			byte messageDigest[] = MD5.MD5Bytes(pwd);
			return BASE64Util.encryptBASE64(messageDigest).trim();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 公钥加密
	 * 
	 * @param desKey
	 * @return
	 * @throws Exception
	 */
	public String encryptKey(String desKey) {
		String enStr = "";
		try {

			// 构造X509EncodedKeySpec对象
			byte[] keyBytes = BASE64Util.decryptBASE64(publicKey);
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
			// KEY_ALGORITHM 指定的加密算法
			KeyFactory keyFactor = KeyFactory.getInstance("RSA");
			RSAPublicKey rsaPublicKey = (RSAPublicKey) keyFactor
					.generatePublic(keySpec);
			byte[] wl9ebankSignBin = desKey.getBytes();
			byte[] plainSignBin = RSAUtil
					.encrypt(rsaPublicKey, wl9ebankSignBin);
			enStr = BASE64Util.encryptBASE64(plainSignBin);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return enStr;
	}

	/**
	 * 移动解密验签
	 * 
	 * @param paramNames
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public boolean verifyResSign(String[] paramNames, Map<String, String> map) {
		try {

			String signHex = map.get("sign");
			if (StringUtil.isEmpty(signHex)) {
				return false;
			}
			// 拼接签名原串
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < paramNames.length; i++) {
				String v = map.get(paramNames[i]);
				if (null != v) {
					sb.append(v);
				}
			}
			// 计算摘要
			String calSignHex = PaySign.md5(sb.toString());
			sb = null;
			// 解密sign
			String decSign = PayEncrypt.decryptMode(getWorkKey(), signHex);
			// 比较
			if (!calSignHex.equalsIgnoreCase(decSign)) {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/*
	 * 移动加密签名
	 * 
	 * @param paramNames
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public String getReqSign(String[] paramNames, Map<String, String> map) {
		String sign = "";
		try {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < paramNames.length; i++) {
				String v = map.get(paramNames[i].trim());
				if (null != v) {
					sb.append(v);
				}
			}
			sign = PayEncrypt.encryptMode(getWorkKey(),
					PaySign.md5(sb.toString()));
			sb = null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return sign;
	}

	/**
	 * 字段加密
	 * 
	 * @param str
	 * @return
	 */
	public String getEncryptDES(String str) {
		try {
			return PayEncrypt.encryptMode(getPingKey(), str);
		} catch (EncException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 字段解密
	 * 
	 * @param str
	 * @return
	 */
	public String getDecryptDES(String str) {
		try {
			return PayEncrypt.decryptMode(getPingKey(), str);
		} catch (EncException e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 平台请求验签
	 * @param paramNames
	 * @param map   mobkey sign  
	 * @return
	 * @throws Exception
	 */
	public  boolean verifyMobRequestSign(String[] paramNames,Map<String,String> map) throws Exception {
		
		byte[] wl9ebankSignBin = Base64.decodeBase64(map.get("mobkey"));
		
		byte[] keyBytes = Base64.decodeBase64(privateKey);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		RSAPrivateCrtKey rsaPrivateKey = (RSAPrivateCrtKey)keyFactory.generatePrivate(pkcs8KeySpec);
		// 私钥解密
		byte[] plainSignBin = RSAUtil.decrypt(rsaPrivateKey, wl9ebankSignBin);
		if(plainSignBin == null){
			
		}
		String deSign = new String(plainSignBin);
		
		String pic = deSign.substring(0, 24);
		String mac = deSign.substring(24);
		
		
		String signHex= map.get("sign");
		if(StringUtils.isEmpty(signHex)){
			return false;
		}
		// 拼接签名原串
		StringBuffer sb = new StringBuffer();
//		System.out.println("验签map:"+map);
		for (int i = 0; i < paramNames.length; i++) {
			String v = map.get(paramNames[i]);
			System.out.println("参数:"+paramNames[i]+"---值---"+v);
			if(null!=v){
				sb.append(v.replace(" ", "+"));
			}
		}
		String p = sb.toString();
		System.out.println("待签报文:"+p);
		// 计算摘要
		String calSignHex = PaySign.md5(p);
		System.out.println("验签calSignHex:"+calSignHex);
		
	    //解密sign
		String decSign= PayEncrypt.decryptMode(mac,signHex.replace(" ", "+"));
		System.out.println("验签decSign:"+decSign);
		// 比较
		if (!calSignHex.equalsIgnoreCase(decSign)) {
			return false;
		}

		return true;
	}
	
	public static void main(String[] args) throws Exception {
		String mobkey = "hzSjDgh7HLeOtvcQ6a01tYaAlQWydH+Kea+8Tqa6dK/MDkIXVTvSwtji0ld4281F7E2F+0Dq7ECCjme9za2skj+39RtYsQSYTu0hznNboAMbAzVeWLM96biZOxjOEcjFYlZXAN+Zrs18lRT8e8YtQxt+N6F4ZkMRco+7LLdNWyA=";
		
		String[] paramNames = {"MerchantId"};
		Map<String, String> map = new HashMap<String, String>();
		map.put("sign", "6ejxMXr1FYGP8WujMDljfKGS/qV0YWvhPaz4YWba02x5YFtWYm0R5g==");
		map.put("MerchantId", "201606281441001");
		map.put("mobkey", mobkey);
		
		EncryptManager e = new EncryptManager();
		System.out.println(e.verifyMobRequestSign(paramNames,map));
	}
}
